﻿using System;

using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Diagnostics;
using Organized;

using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Collisions;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Factories;

namespace Game
{
    class GameplayScreen : GameScreen
    {

        public static string MenuTitle = "New Game";

        //constructor
        public GameplayScreen(String Name) :base(Name)          
        {
                     
               
        }

        Physics Physics;
     


        SkyBox skyBox;

        Terrain terrain;
       //Vehicle vehicle;
        PhysicsVehicle vehicle;

        bool postProcesEnabled = true;
        Color fogColor = Color.Black;

        Random random = new Random();
        AIActor[] animalFlock; // the array of animal objects (the flock)

        AIActor[] animalFlockBIG; // the array of animal objects (the flock)

        //FLOCK SETUP
        int SeperationDistance = 0; // AI seperation distance
        float FlockSeperationSetupDist; // 2 * radiusextra seperation on flock creation



        //VEHICLE SETTINGS
        int VehicleRadius = 35;
       
        int VehicleMass = 25;
        float VehicleGroundFriction = 2.7f;
        float VehicleBouncyness = 1.5f;
        float VehicleSurfaceFriction = 0.1f;

        BaseArea Base;



        Texture2D leatherT;
        Texture2D snowT;

        //AIActor[] animalFlock;
        
        //Post effects
        NiceRendering renderNice;
        MenuScreen consoleScreen;

        Lighting lightBulb;

        public override void Initialize()
        {

           
          
            //add all game components to this screen

            //create a light
            lightBulb = new Lighting(new Vector3(-0.2f, -0.5f, -0.7f), 0.2f);

            // Create a new Camera
            ChaseCamera camera = new ChaseCamera(this);
            camera.CameraPositionOffset = new Vector3(0, 280,650);
            camera.CameraTargetOffset = new Vector3(0, 120, 0);
            camera.CameraTargetDistance = 550.0f;
            camera.cameraLazyness = 40;
            camera.VelocityFOV = true;
            //Add it to the service container
            Engine.Services.AddService(typeof(Camera), camera);

            //turn on physics engine
            Physics = Engine.Services.GetService<Physics>();

            //textures
            leatherT = Engine.Content.Load<Texture2D>("Content/Textures/leather2");          
            terrain = new Terrain(16,170, lightBulb, 2.5f, new Vector3(0, 0, 0), Engine.Content.Load<Texture2D>("Content/Textures/islandheightmega2"),leatherT, 1.0f, this);
            terrain.WireMode = false;
            fogColor = Color.Brown;
            //fogColor = Color.SaddleBrown;
            

            Model boxModel = Engine.Content.Load<Model>("Content/Models/melon");
            Model vModel = Engine.Content.Load<Model>("Content/Models/car4x4");

       
            //create a particle to represent vehicle collision and physics
            PhysicsParticle vehicleParticle = new PhysicsParticle(Physics.PhysicsSimulator, new Vector2(5000,5400), VehicleRadius, VehicleMass, VehicleGroundFriction, VehicleBouncyness, VehicleSurfaceFriction, false,  this);
            vehicle = new PhysicsVehicle(vModel, lightBulb, vehicleParticle, new Vector3(vehicleParticle.Body.Position.X, 1000, vehicleParticle.Body.Position.Y), this);

            vehicle.Scale = new Vector3((float)VehicleRadius / 10f);          
            Random rand = new Random();        
              
            int flock_width = 5;    // horizontal amount of animals to raster
            int flock_height = 10;   // vertical amount of animals to raster          
            animalFlock = createRasteredFlock(17f, 8f, new Vector2(2000, 2000), flock_width, flock_height, boxModel);

            //animalFlockBIG = createRasteredFlock(30f, 25f, new Vector2(2000, 2000), 5, 5, boxModel);


            //create some landmines
            Landmine[] mines = new Landmine[1];
           
                //PhysicsParticle mineP = new PhysicsParticle(Physics.PhysicsSimulator, new Vector2(q * 200 + 1000, q * 200 + 2000), 15, 1, 1, 1, 1, true, this);
                Vector3 Pos = new Vector3(1200,500, 1200);
                mines[0] = new Landmine(boxModel, lightBulb,  Pos, terrain.heightMapData, Physics.PhysicsSimulator, this);
                mines[0].Scale = new Vector3(0.5f);          
            


            //send the heighmap data to our terrain responding objects
            vehicle.SetHeightMapData(terrain.heightMapData);

            foreach (AIActor actor in animalFlock)
            {
                actor.SetHeightMapData(terrain.heightMapData);
            }
           

            skyBox = new SkyBox(lightBulb, Vector3.Zero, this);
            skyBox.Scale = new Vector3(3000.0f);

            camera.setHeightMapData(terrain.heightMapData);
            camera.addTarget(vehicle);


            renderNice = new NiceRendering(camera, Engine.GraphicsDevice.Viewport.Width, Engine.GraphicsDevice.Viewport.Height, this);
            renderNice.Visible = false;


            consoleScreen = new ConsoleScreen(renderNice, "ConsoleScreen");
           
            base.Initialize();
           
        }

        AIActor animal;


        private void UpdateFlock(){
         
            
          
           
            for (int z = 0; z < animalFlock.Length; z++)
            {

                animal = animalFlock[z];

                animal.SetupReact();

                    for (int u = 0; u < animalFlock.Length; u++)
                    {

                        if (animalFlock[u] != animal)
                        {
                            animal.ReactTo(animalFlock[u]);
                        }

                    }
                    animal.FinishReact();
                
            }   
           

        }
        

        private AIActor[] createRasteredFlock(float AnimalSize, float AnimalMass, Vector2 pos, int width, int height, Model model)
        {
           
            FlockSeperationSetupDist = 10f * AnimalSize;
            //create an array to store the animals
            AIActor[] flock = new AIActor[width * height];
            int count = 0;
            float pos_offset = AnimalSize + SeperationDistance + FlockSeperationSetupDist;
            for (int x = 0; x < width; x++)
            {
                

                for (int y = 0; y < height; y++)
                {
                    float AnimalSizeVar = AnimalSize + ((float)random.NextDouble() * 2f);
                    //Vector2 Position = new Vector2(pos.X + x * pos_offset, pos.Y + y * pos_offset);
                    Vector2 Position = new Vector2((float)(random.NextDouble() * 2000), (float)(random.NextDouble() * 200));
                    Position += pos;
                    PhysicsParticle particle = new PhysicsParticle(Physics.PhysicsSimulator, Position, AnimalSizeVar, AnimalMass, 0.3f, 0.5f, 0.01f, false, this);
                    AIActor actor = new AIActor(model, lightBulb, particle, new Vector3(particle.Position.X, 300f, particle.Position.Y), vehicle, count, this);
                    actor.copyParticleAngle = false;
                    //set actor model scale
                    flock[count++] = actor;
                    actor.Scale = new Vector3(AnimalSizeVar / 10f);
                    
                    
                }
            }
            //return the animal array
            return flock;

        }      
     

        public override void Draw(ComponentPredicate DrawPredicate)
        {
            Engine.GraphicsDevice.Clear(Color.Black);

           
            Engine.GraphicsDevice.RenderState.FogEnable = true;
            Engine.GraphicsDevice.RenderState.FogStart = 1000f;
            Engine.GraphicsDevice.RenderState.FogDensity = 0.4f;
            Engine.GraphicsDevice.RenderState.FogEnd = 4000f;
            Engine.GraphicsDevice.RenderState.FogTableMode = FogMode.Linear;
            Engine.GraphicsDevice.RenderState.FogColor = fogColor;          

            Engine.GraphicsDevice.RenderState.DepthBufferWriteEnable = true;
            base.Draw(DrawPredicate);

            //blur the screen
            if (postProcesEnabled)
            {
                renderNice.Draw();
            }
        }


        public override void Update()
        {


           
            KeyboardDevice keyboard = Engine.Services.GetService<KeyboardDevice>();
            MouseDevice mouse = Engine.Services.GetService<MouseDevice>();
            //ChaseCamera cam = (ChaseCamera)Engine.Services.GetService<Camera>();

            Vector3 inputModifier = new Vector3(
                (keyboard.IsKeyDown(Keys.A) ? -5 : 0) + (keyboard.IsKeyDown(Keys.D) ? 5 : 0),
                (keyboard.IsKeyDown(Keys.Q) ? -5 : 0) + (keyboard.IsKeyDown(Keys.E) ? 5 : 0),
                (keyboard.IsKeyDown(Keys.W) ? -5 : 0) + (keyboard.IsKeyDown(Keys.S) ? 5 : 0)
            );

            //update physics engine

            if (!consoleScreen.Visible)
            {
                vehicle.HandleInput(keyboard.State);
            }
            if (keyboard.WasKeyReleased(Keys.Q))
            {
                postProcesEnabled = !postProcesEnabled;
            }

            if (keyboard.WasKeyReleased(Keys.F1))
            {
                consoleScreen.Visible = !consoleScreen.Visible;
                consoleScreen.BlocksInput = !consoleScreen.BlocksInput;
                
            }

      
           UpdateFlock();
        
           base.Update();


        }

        
    }
}
